#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <functional>
#include <map>

#include "Common.hpp"
#include "threadpool.hpp"
#include "LockGuard.hpp"
#include "log.hpp"
#include "Database.hpp"
#include "Serialize.hpp"

using task_t = std::function<void()>;

class MessageRoute
{
private:
    //////
    const std::string host = "localhost";
    const std::string user = "connector";
    const std::string password = "5397687p";
    const std::string db = "conn";
    const unsigned int port = 3306; // 确认你的MySQ
public:
    MessageRoute()
        : _count(0), _db(host, user, password, db, port)
    {
        if (!_db.ConnectToSql())
        {
            exit(CONNECTSQL_ERROR);
        }
        LOG(FATAL,"mysql error");
        pthread_mutex_init(&_mutex, nullptr);
    }
    void AddUser(InetAddr &addr, int sockfd) // 将在线人数插入
    {                                        // 检查 sockfd 是否有效（假设 -1 是无效的）
        if (sockfd < 0)
        {
            LOG(ERROR, "无效的 sockfd: %d\n", sockfd);  
        }
        LockGuard guard(&_mutex);

        // 检查用户是否已存在，基于 addr
        if (_online_user.find(addr) == _online_user.end())
        {
            // 用户不存在，插入新用户
            _online_user.insert(std::make_pair(addr, sockfd));
            // pushtosql 或其他操作
            LOG(INFO, "New user added, user IP: %s\n", addr.Ip().c_str());
        }
        else
        {
            // 用户已经存在，记录日志或处理其他逻辑
            LOG(INFO, "User already exists, user IP: %s\n", addr.Ip().c_str());  
        }     
    }

    void DelUser(InetAddr &addr)
    {
        LockGuard guard(&_mutex);
        auto it = _online_user.find(addr);
        if (it != _online_user.end())
        {
            _online_user.erase(it);
            LOG(INFO, "User removed, userIP:%s\n", addr.Ip().c_str());
        }
    }

    void TextMessageHelper(int sockfd, std::string &message, std::string &name)
    {
        LockGuard guard(&_mutex);
        const std::string msg = _serialze.EncodeTextResponse(message, name);
        for (auto user : _online_user)
        {
            InetAddr User = user.first;
            struct sockaddr_in User_Addr = User.Addr();
            int sockfd = user.second;
            LOG(DEBUG, "send message :%s", msg.c_str());
            _messagepool.emplace_back(msg);
            ::sendto(sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr *)&User_Addr, sizeof(User_Addr)); // 调用原生接口 发信息
        }
    }
    void HistoryHelper(int sockfd, InetAddr &who) // 进行消息拉取
    {
        LOG(DEBUG, "send history to%s ",who.Ip().c_str());
        LockGuard guard(&_mutex);
        struct sockaddr_in userAddr = who.Addr();
        for (auto &message : _messagepool)
        {
            ::sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&userAddr, sizeof(userAddr)); // 调用原生接口 发信息
        }
    }
    void LoginHelper(int sockfd, InetAddr &who, bool check)
    {
        LockGuard guard(&_mutex);
        struct sockaddr_in userAddr = who.Addr();
        std::string message;
        if (check)
        {
            message = LOG_SUCCESS;
        }
        else
        {
            message = LOG_FAIL;
        }
        LOG(DEBUG, "message:%s", message.c_str());
        ::sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&userAddr, sizeof(userAddr));
    }
    void RegisterHelper(int sockfd, InetAddr &who, bool check) // 错误返回Occupied
    {
        LockGuard guard(&_mutex);
        struct sockaddr_in userAddr = who.Addr();
        std::string message;
        if (check)
            message = REG_SUCCESS;
        else
            message = REG_OCPIED;
        ::sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&userAddr, sizeof(userAddr));
    }
    void QuitHelper(InetAddr &who)
    {
        LockGuard guard(&_mutex);
        std::string message = QUIT_SIGN + SEP + who.Ip().c_str();
        for (auto &user : _online_user)
        {
            InetAddr User = user.first;
            struct sockaddr_in User_Addr = User.Addr();
            int sockfd = user.second;
            ::sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&User_Addr, sizeof(User_Addr)); // 调用原生接口 发信息
        }
    }
    
    void Route(int fd, std::string message, InetAddr who)
    {
        std::string SIGN = _serialze.GetFirstSIGN(message);
        std::string user;
        std::string Message;

        _serialze.Decode_Text(message, SIGN, user, Message);
        // 管理是什么类型的消息
        // 处理用户信息
        LOG(DEBUG, "SIGN %s", SIGN.c_str());
        if (SIGN == CHAT_SIGN) // 正常消息
        {                      // 处理文本 图片 语音 文件
            // std::string new_message = _serialze.GetRestPart(message);
            // std::string rest_message;
            // MessageType type = _serialze.GetFirstMsgSIGN(new_message, rest_message);
            // if (type = TEXT_TYPE)
            // {
            //     _messagepool.emplace_back(rest_message);
            //     ++_count;
            // }
            // else if (type == IMAGE_TYPE)
            // {
            //     ;
            // }
            // else if (type == FILE_TYPE)
            // {
            //     ;
            // }
            // else if (type == SPEECH_TYPE)
            // {
            //     ;
            // }
            LOG(DEBUG, "message:%s user:%s", Message.c_str(), user.c_str());
            task_t t = std::bind(&MessageRoute::TextMessageHelper, this, fd, Message, user);
            threadpool<task_t>::Getinstance()->Enqueue(t);
        }
        if (SIGN == HIS_SIGN) // 用户拉取历史消息
        {
            task_t t = std::bind(&MessageRoute::HistoryHelper, this, fd, who);
            LOG(INFO, "user:%s PULL MESSAGE", who.Ip().c_str());
            threadpool<task_t>::Getinstance()->Enqueue(t);
        }
        else if (SIGN == LOG_SIGN)
        {
            std::pair<std::string, std::string> user = _serialze.Decode_user_pass(message);
            bool check;
            std::cout << user.first << user.second << std::endl;
            AddUser(who,fd);
            if (!_db.Login(user.first, user.second))
            {
                check = false;
                LOG(DEBUG, "user:%s LOGIN FAILL!", who.Ip().c_str());
            }
            else
            {
                check =true;
                if (check)
                {
                    LOG(INFO, "user:%s LOGIN SUCCESE!", who.Ip().c_str());   
                }
                else
                {
                    LOG(DEBUG, "user:%s LOGIN ALREADY IN!", who.Ip().c_str());
                }
            }
            task_t t = std::bind(&MessageRoute::LoginHelper, this, fd, who, check); // 将检查位传入
            threadpool<task_t>::Getinstance()->Enqueue(t);
        }
        else if (SIGN == REG_SIGN)
        {
            std::pair<std::string, std::string> user = _serialze.Decode_user_pass(message);
            bool check;
            if (!_db.UserExists(user.first))
            {
                check = true;
                AddUser(who, fd);
                _db.Register(user.first, user.second);
                LOG(DEBUG, "user:%s have no repeate!", who.Ip().c_str());
            }
            else
            {
                check = false;
                LOG(INFO, "user:%s repeate", who.Ip().c_str());
            }

            task_t t = std::bind(&MessageRoute::RegisterHelper, this, fd, who, check);
            LOG(DEBUG, "user:%s REGIN!", who.Ip().c_str());
            threadpool<task_t>::Getinstance()->Enqueue(t);
        }
        else if (SIGN == QUIT_SIGN)
        {
            DelUser(who);
            task_t t = std::bind(&MessageRoute::QuitHelper, this, who);
            threadpool<task_t>::Getinstance()->Enqueue(t);
        }
        if (_count >= 50)
            MessagPool_keep();
    }
    ~MessageRoute()
    {
        pthread_mutex_destroy(&_mutex);
    }

private:
    void MessagPool_keep()
    {
        if (_messagepool.size() > 50)
        {
            _messagepool.erase(_messagepool.begin(), _messagepool.end() - 40);
        }
    }

private:
    std::map<InetAddr, int> _online_user; // ip sockfd
    pthread_mutex_t _mutex;
    std::vector<std::string> _messagepool;
    //////////////////////////////////
    Database _db;
    //////////////////////////////
    int _count;
    ///////////////////////////////
    Serialize _serialze;
};
